package online.longzipeng.back.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.netty.channel.Channel;
import online.longzipeng.back.common.enums.TeamMessageStatusEnum;
import online.longzipeng.back.common.exception.MessageException;
import online.longzipeng.back.mapper.*;
import online.longzipeng.back.notify.UserChanelRel;
import online.longzipeng.back.pojo.dto.NotifyMessage;
import online.longzipeng.back.pojo.entity.*;
import online.longzipeng.back.pojo.enums.MessageActionEnum;
import online.longzipeng.back.pojo.param.TeamDeleteParam;
import online.longzipeng.back.pojo.param.TeamQueryParam;
import online.longzipeng.back.pojo.vo.TeamMessageVo;
import online.longzipeng.back.pojo.vo.TeamVo;
import online.longzipeng.back.pojo.vo.UserVo;
import online.longzipeng.back.service.TeamService;
import online.longzipeng.back.utils.NotifyUtils;
import online.longzipeng.back.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author lzp
 */
@Service
public class TeamServiceImpl implements TeamService {

    @Autowired
    private TeamMapper teamMapper;
    @Autowired
    private UserTeamMapper userTeamMapper;
    @Autowired
    private TeamMessageMapper teamMessageMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BillMapper billMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(Team team) {
        // 参数校验
        if (StrUtil.isBlank(team.getName())) {
            throw new MessageException("必须填写团队的名称！！");
        }
        Long userId = UserUtils.getUserId();
        // 如果有id，走二次编辑操作
        if (ObjectUtil.isNotNull(team.getId())) {
            // 只有团队的创建者能够编辑团队
            if (ObjectUtil.equal(userId, team.getCreateBy())) {
                throw new MessageException("只有团队的创建者才能够编辑团队！！");
            }
            // 先查一次，看看该用户是否已经创建了相同的团队
            this.teamCheckExist(userId, team.getName());
            Team teamOld = teamMapper.selectOne(Wrappers.<Team>lambdaQuery().eq(Team::getId, team.getId()));
            BeanUtil.copyProperties(team, teamOld);
            teamMapper.updateById(teamOld);
        } else {
            // 先查一次，看看该用户是否已经创建了相同的团队
            this.teamCheckExist(userId, team.getName());
            // 走新增
            team.setCreateBy(userId);
            team.setUpdateBy(userId);
            teamMapper.insert(team);
            // 把自己加入到团队成员中
            UserTeam userTeam = new UserTeam();
            userTeam.setTeamId(team.getId());
            userTeam.setUserId(userId);
            userTeamMapper.insert(userTeam);
        }
    }

    /**
     * 判断当前用户新增或二次编辑保存的团队是否已经创建过
     *
     * @param userId 当前登录用户id
     * @param name   新增或二次编辑的团队名称
     */
    private void teamCheckExist(Long userId, String name) {
        Team teamOld = teamMapper.selectOne(Wrappers.<Team>lambdaQuery().eq(Team::getCreateBy, userId).eq(Team::getName, name));
        if (ObjectUtil.isNotNull(teamOld)) {
            throw new MessageException("你已经创建过该名称的团队！！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void join(Long teamId, Long userId) {
        // 先判断该用户是否已加入团队 存在
        UserTeam userTeamExist = userTeamMapper.selectOne(Wrappers.<UserTeam>lambdaQuery().eq(UserTeam::getTeamId, teamId).eq(UserTeam::getUserId, userId));
        if (ObjectUtil.isNotNull(userTeamExist)) {
            throw new MessageException("你已加入该团队！！");
        }
        // 团队新增一个成员
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(teamId);
        userTeam.setUserId(userId);
        userTeamMapper.insert(userTeam);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long teamId) {
        Long userId = UserUtils.getUserId();
        Team team = teamMapper.selectOne(Wrappers.<Team>lambdaQuery().eq(Team::getId, teamId));
        if (ObjectUtil.isNull(team)) {
            throw new MessageException("团队不存在！！");
        }
        // 只有团队创建者才能解散团队
        if (!ObjectUtil.equal(userId, team.getCreateBy())) {
            throw new MessageException("你没有权限删除该团队！！");
        }
        // 先删除团队，再删除团队所有成员
        teamMapper.delete(Wrappers.<Team>lambdaQuery().eq(Team::getId, teamId));
        userTeamMapper.update(null, Wrappers.<UserTeam>lambdaUpdate().set(UserTeam::getDeleteFlag, 1).eq(UserTeam::getTeamId, teamId));
        // 删除团队所有账单
        billMapper.delete(Wrappers.<Bill>lambdaQuery().eq(Bill::getTeamId, teamId));
    }

    @Override
    public List<TeamVo> list(TeamQueryParam param) {
        return teamMapper.list(param);
    }

    @Override
    public void invite(TeamMessage teamMessage) {
        // 参数校验
        if (ObjectUtil.isNull(teamMessage.getTeamId()) || ObjectUtil.isNull(teamMessage.getReceiveUserId())) {
            throw new MessageException("团队和接收者都不能为null");
        }
        // 查询接收者信息
        User receiveUser = userMapper.selectById(teamMessage.getReceiveUserId());
        if (ObjectUtil.isNull(receiveUser)) {
            throw new MessageException("邀请的用户不存在！！");
        }
        // 校验是否重复发送消息
        Integer count = teamMessageMapper.selectCount(Wrappers.<TeamMessage>lambdaQuery()
                .eq(TeamMessage::getTeamId, teamMessage.getTeamId())
                .eq(TeamMessage::getReceiveUserId, teamMessage.getReceiveUserId())
                .eq(TeamMessage::getStatus, TeamMessageStatusEnum.PENDING));
        if (count > 0) {
            throw new MessageException("请误重复邀请！！");
        }
        // 获取发送者
        User loginUser = UserUtils.getLoginUser();
        teamMessage.setSendUserId(loginUser.getId());
        // 团队校验
        Team team = teamMapper.selectOne(Wrappers.<Team>lambdaQuery().eq(Team::getId, teamMessage.getTeamId()));
        if (ObjectUtil.isNull(team)) {
            throw new MessageException("团队不存在！！");
        }
        // 将消息存入数据库
        teamMessageMapper.insert(teamMessage);
        // 推送消息给接收人
        Channel channel = UserChanelRel.get(teamMessage.getReceiveUserId());
        if (ObjectUtil.isNotNull(channel)) {
            // 用户在线
            NotifyUtils.pushMessage(channel, JSON.toJSONString(NotifyMessage.builder().action(MessageActionEnum.GROUP_INVITATION).content(new StringBuilder().append(loginUser.getNickName()).append("邀请您加入【").append(team.getName()).append("】").toString()).data(teamMessage.getId()).build()));
        } else {
            // 用户离线 无所谓，会在消息列表中拉取到
        }
    }

    @Override
    public TeamVo detail(Long id) {
        TeamVo team = teamMapper.detail(id);
        Long userId = UserUtils.getUserId();
        // 如果团队创建者就是登录用户，则可以编辑
        if (ObjectUtil.equal(team.getCreateBy(), userId)) {
            team.setCanEdit(true);
        }
        if (ObjectUtil.isNotNull(team)) {
            // 查找团队中所有的成员
            List<UserVo> users = userMapper.listByTemId(team.getId());
            team.setUsers(users);
            team.setUserCount(users.size());
        }
        return team;
    }

    @Override
    public List<TeamMessageVo> getTeamMessages() {
        Long userId = UserUtils.getUserId();
        return teamMessageMapper.getTeamMessages(userId);
    }

    @Override
    public void deleteUsers(TeamDeleteParam param) {
        if (CollUtil.isNotEmpty(param.getDeleteUsers()) && ObjectUtil.isNotNull(param.getId())) {
            // 删除在指定团队中的指定用户
            userTeamMapper.delete(Wrappers.<UserTeam>lambdaQuery().eq(UserTeam::getTeamId, param.getId()).in(UserTeam::getUserId, param.getDeleteUsers()));
        }
    }

    @Override
    public void deleteMessage(Long id) {
        Long userId = UserUtils.getUserId();
        // 先查询消息
        TeamMessage teamMessage = teamMessageMapper.selectById(id);
        if (ObjectUtil.isNull(teamMessage)) {
            throw new MessageException("消息不存在！！请刷新页面");
        }
        // 如果是消息发送者
        if (ObjectUtil.equal(userId, teamMessage.getSendUserId())) {
            /// 如果消息接收者也删除了消息，那么逻辑删除消息
            if (ObjectUtil.equal(teamMessage.getReceiveDeleteFlag(), 1)) {
                teamMessage.setDeleteFlag(1);
            }
            teamMessage.setSendDeleteFlag(1);
        } else {
            // 消息接收者删除消息
            /// 如果消息发送者也删除了消息，那么逻辑删除消息
            if (ObjectUtil.equal(teamMessage.getSendDeleteFlag(), 1)) {
                teamMessage.setDeleteFlag(1);
            }
            teamMessage.setReceiveDeleteFlag(1);
            /// 如果此时状态为待定，则修改状态为拒绝
            if (ObjectUtil.equal(teamMessage.getStatus(), TeamMessageStatusEnum.PENDING.getStatus())) {
                teamMessage.setStatus(TeamMessageStatusEnum.REJECT.getStatus());
            }
        }
        teamMessageMapper.updateById(teamMessage);
    }

    @Override
    public void handleMessage(Long id, Integer status) {
        // 先查询消息
        TeamMessage teamMessage = teamMessageMapper.selectById(id);
        teamMessage.setStatus(status);
        // 先查询团队是否存在
        Team team = teamMapper.selectById(teamMessage.getTeamId());
        if (ObjectUtil.isNull(team)) {
            teamMapper.deleteById(id);
            throw new MessageException("团队不存在，已自动删除消息！！");
        }
        // 如果是接受，则需要加入对应团队
        String description = "拒绝";
        if (ObjectUtil.equal(status, TeamMessageStatusEnum.AGREE.getStatus())) {
            UserTeam userTeam = new UserTeam(teamMessage.getTeamId(), UserUtils.getUserId());
            userTeamMapper.insert(userTeam);
            description = "同意";
        }
        // 推送消息给消息发送人
        Channel channel = UserChanelRel.get(teamMessage.getSendUserId());
        if (ObjectUtil.isNotNull(channel)) {
            // 用户在线
            NotifyUtils.pushMessage(channel, JSON.toJSONString(
                    NotifyMessage.builder()
                            .action(MessageActionEnum.GROUP_INVITATION)
                            .content(new StringBuilder().append(UserUtils.getLoginUser().getNickName()).append(description).append("加入【").append(team.getName()).append("】").toString())
                            .data(teamMessage.getId()).build()));
        } else {
            // 用户离线 无所谓，会在消息列表中拉取到
        }
        teamMessageMapper.updateById(teamMessage);
    }
}